home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / NE2.ASM < prev    next >
Assembly Source File  |  1991-01-26  |  32KB  |  1,295 lines

  1. ; Packet driver for Novell's NE/2
  2. ; Written by:
  3. ;    Eric Henderson
  4. ;    Brigham Young University
  5. ;    
  6. ; Based on the "generic" packet driver by Russell Nelson with help
  7. ; from the western digital pd by Russell Nelson.
  8. ; 80[123]86 processor support lifted from 3com driver by permission
  9. ;    from Russell Nelson
  10. ;
  11. ;   Portions (C) Copyright 1990 BYU
  12.  
  13. version    equ    5
  14.  
  15. .286
  16.     include    defs.asm
  17.  
  18. code    segment    byte public
  19.     assume    cs:code, ds:code
  20.  
  21. ;*****************************************************************************
  22. ;
  23. ;    NE/2 controller board offsets
  24. ;    IO port definition (BASE in io_addr)
  25. ;*****************************************************************************
  26. ADDROM  EQU    10h            ; LAN Address ROM
  27. RACK    EQU    10h            ; NE2 Port Window 
  28. NERESET EQU    20h            ; Issue a read for reset
  29.  
  30. ; 8390 LAN Controller (page0) register offset for read and write 
  31. CMDR    EQU    00h            ; command register for read & write
  32. CLDA0    EQU    01h            ; current local dma addr 0 for read
  33. PSTART    EQU    01h            ; page start register for write
  34. CLDA1    EQU    02h            ; current local dma addr 1 for read
  35. PSTOP    EQU    02h            ; page stop register for write
  36. BNRY    EQU    03h            ; boundary reg for rd and wr
  37. TSR    EQU    04h            ; tx status reg for rd
  38. TPSR    EQU    04h            ; tx start page start reg for wr    
  39. NCR    EQU    05h            ; number of collision reg for rd
  40. TBCR0    EQU    05h            ; tx byte count 0 reg for wr
  41. FIFO    EQU    06h            ; FIFO for rd
  42. TBCR1    EQU    06h            ; tx byte count 1 reg for wr
  43. ISR    EQU    07h            ; interrupt status reg for rd and wr
  44. CRDA0    EQU    08h            ; current remote dma address 0 for rd
  45. RSAR0    EQU    08h            ; remote start address reg 0  for wr
  46. CRDA1    EQU    09h            ; current remote dma address 1 for rd
  47. RSAR1    EQU    09h            ; remote start address reg 1 for wr
  48. RBCR0    EQU    0Ah            ; remote byte count reg 0 for wr
  49. RBCR1    EQU    0Bh            ; remote byte count reg 1 for wr
  50. RSR    EQU    0Ch            ; rx status reg for rd
  51. RCRWD    EQU    0Ch            ; rx configuration reg for wr
  52. CNTR0    EQU    0Dh            ; tally cnt 0 for frm alg err for rd
  53. TCR    EQU    0Dh            ; tx configuration reg for wr
  54. CNTR1    EQU    0Eh            ; tally cnt 1 for crc err for rd
  55. DCR    EQU    0Eh            ; data configuration reg for wr
  56. CNTR2    EQU    0Fh            ; tally cnt 2 for missed pkt for rd
  57. IMR    EQU    0Fh            ; interrupt mask reg for wr
  58. ; 8390 LAN Controller (page1) register offset for read and write 
  59. PAR0    EQU    01h             ; physical addr reg 0 for rd and wr
  60. PAR1    EQU    02h             ; physical addr reg 1 for rd and wr
  61. PAR2    EQU    03h             ; physical addr reg 2 for rd and wr
  62. PAR3    EQU    04h             ; physical addr reg 3 for rd and wr
  63. PAR4    EQU    05h             ; physical addr reg 4 for rd and wr
  64. PAR5    EQU    06h             ; physical addr reg 5 for rd and wr
  65. CURR    EQU    07h            ; current page reg for rd and wr
  66. MAR0    EQU    08h            ; multicast addr reg 0 fro rd and WR
  67. MAR1    EQU    09h            ; multicast addr reg 1 fro rd and WR
  68. MAR2    EQU    0Ah            ; multicast addr reg 2 fro rd and WR
  69. MAR3    EQU    0Bh            ; multicast addr reg 3 fro rd and WR
  70. MAR4    EQU    0Ch            ; multicast addr reg 4 fro rd and WR
  71. MAR5    EQU    0Dh            ; multicast addr reg 5 fro rd and WR
  72. MAR6    EQU    0Eh            ; multicast addr reg 6 fro rd and WR
  73. MAR7    EQU    0Fh            ; multicast addr reg 7 fro rd and WR
  74.  
  75. ;***********************************************************************
  76. ;
  77. ;    8003 control register operations
  78. ;***********************************************************************
  79.  
  80. MSK_RESET    EQU    80h            ; reset LAN controller
  81. MSK_ENASH    EQU    40h        ; enable PC access to shared mem
  82. MSK_DECOD    EQU    3Fh         ; ???? memory decode bits, corresponding
  83.                     ; to SA 18-13. SA 19 assumed to be 1
  84. ;***********************************************************************
  85. ;
  86. ;    8390 CMDR MASK
  87. ;***********************************************************************
  88.  
  89. MSK_STP        EQU    01h        ; software reset, take 8390 off line
  90. MSK_STA        EQU    02h        ; activate the 8390 NIC
  91. MSK_TXP        EQU    26h        ; initial txing of a frm  (With DMA)
  92. MSK_RD2        EQU    20h        ; abort remote DMA
  93. MSK_PG0        EQU    00h        ; select register page 0
  94. MSK_PG1        EQU    40h        ; select register page 1
  95. MSK_PG2        EQU    80h        ; select register page 2
  96. MSK_DMA_RD    EQU    0ah        ; start DMA read
  97. MSK_DMA_WR    EQU    12h        ; start DMA write
  98.  
  99. ;***********************************************************************
  100. ;
  101. ;    8390 ISR & IMR MASK
  102. ;***********************************************************************
  103.  
  104. MSK_PRX  EQU    01h        ; rx with no error
  105. MSK_PTX  EQU    02h        ; tx with no error
  106. MSK_RXE  EQU    04h        ; rx with error
  107. MSK_TXE  EQU    08h        ; tx with error
  108. MSK_OVW  EQU    10h        ; overwrite warning
  109. MSK_CNT  EQU    20h        ; MSB of one of the tally counters is set
  110. MSK_RDC  EQU    40h        ; remote dma completed
  111. MSK_RST     EQU    80h        ; reset state indicator
  112. MaskByte        equ    0
  113. UnmaskByte        equ    1fh
  114. InterruptMask        equ    0fh
  115.  
  116. ;***********************************************************************
  117. ;
  118. ;    8390 DCR MASK
  119. ;***********************************************************************
  120.  
  121. MSK_WTS EQU    01h        ; word transfer mode selection
  122. MSK_BOS    EQU    02h        ; byte order selection
  123. MSK_LAS    EQU    04h        ; long addr selection
  124. MSK_BMS    EQU    08h        ; burst mode selection
  125. MSK_ARM    EQU    10h        ; atuoinitialize remote
  126. MSK_FT00 EQU    00h        ; burst lrngth selection
  127. MSK_FT01 EQU    20h        ; burst lrngth selection
  128. MSK_FT10 EQU    40h        ; burst lrngth selection
  129. MSK_FT11 EQU    60h        ; burst lrngth selection
  130.  
  131. ;***********************************************************************
  132. ;
  133. ;    8390 RCR MASK
  134. ;***********************************************************************
  135.  
  136. MSK_SEP EQU    01h        ; save error pkts
  137. MSK_AR     EQU    02h        ; accept runt pkt
  138. MSK_AB     EQU    04h        ; accept broadcast 
  139. MSK_AM     EQU    08h        ; accept multicast 
  140. MSK_PRO    EQU    10h        ; promiscuous physical
  141.                 ; accept all pkt with physical adr
  142. MSK_MON EQU    20h        ; monitor mode
  143.  
  144. ;***********************************************************************
  145. ;
  146. ;    8390 TCR MASK
  147. ;***********************************************************************
  148.  
  149. MSK_CRC EQU    01h        ; inhibit CRC, do not append crc
  150. MSK_LB01 EQU    06h        ; encoded loopback control
  151. MSK_ATD    EQU    08h        ; auto tx disable
  152. MSK_OFST EQU    10h        ; collision offset enable 
  153.  
  154. ;***********************************************************************
  155. ;
  156. ;    8390 RSR MASK
  157. ;***********************************************************************
  158.  
  159. SMK_PRX  EQU    01h        ; rx without error
  160. SMK_CRC  EQU    02h        ; CRC error
  161. SMK_FAE  EQU    04h        ; frame alignment error
  162. SMK_FO   EQU    08h        ; FIFO overrun
  163. SMK_MPA  EQU    10h        ; missed pkt
  164. SMK_PHY  EQU    20h        ; physical/multicase address
  165. SMK_DIS  EQU    40h        ; receiver disable. set in monitor mode
  166. SMK_DEF     EQU    80h        ; deferring
  167.  
  168. ;***********************************************************************
  169. ;
  170. ;    8390 TSR MASK
  171. ;***********************************************************************
  172.  
  173. SMK_PTX  EQU    01h        ; tx without error
  174. SMK_DFR  EQU    02h        ; non deferred tx
  175. SMK_COL  EQU    04h        ; tx collided
  176. SMK_ABT  EQU    08h        ; tx aboort because of excessive collisions
  177. SMK_CRS  EQU    10h        ; carrier sense lost
  178. SMK_FU   EQU    20h        ; FIFO underrun
  179. SMK_CDH  EQU    40h        ; collision detect heartbeat
  180. SMK_OWC     EQU    80h        ; out of window collision
  181.  
  182. ;***********************************************************************
  183. ;
  184. ;    on board memory constant definition
  185. ;***********************************************************************
  186. ; for rcv buff ring of onboard mem
  187. START_PG EQU    46h                  ; start at page 46
  188. STOP_PG  EQU    80h            ; end at page 80 
  189. ; for tx buff of shr mem
  190. TB_SIZE EQU    1            ; number of tb buff in shr mem
  191. TB_PGNO EQU    6            ; number of pages in one tb buff
  192.  
  193. EIGHTBITSLOT    db    0        ;8-bit machine flag
  194. Path        dw    ?
  195. RxPath        dw    ?
  196.  
  197. extrn        is_at: byte
  198.  
  199.     public    int_no, io_addr
  200. int_no        db    3,0,0,0        ;must be four bytes long for get_number.
  201. io_addr        dw    1000h,0        ; I/O address for card (jumpers)
  202. my_eaddr      db    6 dup(?)    ; 6 byte LAN address
  203. m_channel     dw     0        ; micro channel flag    
  204. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  205.  
  206. rd_NE    MACRO    port
  207.     mov    DX, CS:io_addr
  208.     add    DX, port        ; DX contains address of port
  209.     in    AL, DX            ; AL contains data read from port
  210.     ENDM
  211.  
  212. wr_NE    MACRO    port
  213.     mov    DX, CS:io_addr
  214.     add    DX, port        ; DX contains address of port
  215.     out    DX, AL            ; AL contains data to be written to port
  216.     ENDM
  217.  
  218. ReceiveHeaderStructure    struc
  219.    RReceiveStatus    db    ?
  220.    RNextBuffer        db    ?
  221.    RByteCount        dw    ?
  222.  
  223.    RDestinationAddress    db    6 dup(?)
  224.    RSourceAddress    db    6 dup(?)
  225.    RPacketLength    dw    ?
  226.    RChecksum        dw    ?
  227.    RRPacketLength    dw    ?
  228.    RTranControl        db    ?
  229.    RHPacketType        db    ?
  230.    RDestinationNet    db    4 dup(?)
  231.    RDestinationNode    db    6 dup(?)
  232.    RDestinationSocket    dw    ?
  233. ReceiveHeaderStructure    ends
  234.  
  235. ReceiveHeader    ReceiveHeaderStructure    <>
  236.  
  237. Current                equ    InterruptStatus
  238. CurrentDMA0            equ    RemoteStartAddress0
  239. CurrentDMA1            equ    RemoteStartAddress1
  240. ForRSTBit            equ    80h
  241.  
  242. NIC    struc
  243.     Command            db    ?
  244.     PageStart        db    ?
  245.     PageStop        db    ?
  246.     Boundry            db    ?
  247.     TransmitStatus        db    ?
  248.     TransmitByteCount0    db    ?
  249.     TransmitByteCount1    db    ?
  250.     InterruptStatus        db    ?
  251.     RemoteStartAddress0    db    ?
  252.     RemoteStartAddress1    db    ?
  253.     RemoteByteCount0    db    ?
  254.     RemoteByteCount1    db    ?
  255.     ReceiveConfiguration    db    ?
  256.     TransmitConfiguration    db    ?
  257.     DataConfiguration    db    ?
  258.     IntMask            db    ?
  259.     DataPort        db    ?
  260.                 db    15 dup (?)
  261.     Reset            db    ?
  262. NIC    ends
  263.  
  264. BLUEBOOK    equ    1
  265. IEEE8023    equ    11
  266.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  267. driver_class    db    BLUEBOOK, IEEE8023,  0    ;from the packet spec
  268. driver_type    dw    0ffffh        ;Wild card matches any type
  269. driver_name    db    'NE/2',0    ;name of the driver.
  270. driver_function    db    2
  271. parameter_list    label    byte
  272.     db    1    ;major rev of packet driver
  273.     db    9    ;minor rev of packet driver
  274.     db    14    ;length of parameter list
  275.     db    EADDR_LEN    ;length of MAC-layer address
  276.     dw    GIANT    ;MTU, including MAC headers
  277.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  278.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  279.     dw    0    ;(# of successive xmits) - 1
  280.     dw    0    ;Interrupt # to hook for post-EOI
  281.             ;processing, 0 == none,
  282.  
  283. mcast_list_bits db      0,0,0,0,0,0,0,0 ;Bit mask from last set_multicast_list
  284. mcast_all_flag  db      0               ;Non-zero if hware should have all
  285.  
  286.     public    rcv_modes
  287. rcv_modes    dw    7        ;number of receive modes in our table.
  288.         dw    0        ;there is no mode 1.
  289.         dw    rcv_mode_1
  290.         dw    rcv_mode_2
  291.         dw    rcv_mode_3
  292.         dw    rcv_mode_4
  293.         dw    rcv_mode_5
  294.         dw    rcv_mode_6
  295. rxcr_bits       db      MSK_AB        ; Default to ours plus multicast
  296.  
  297.  
  298.     public    as_send_pkt
  299. ; The Asynchronous Transmit Packet routine.
  300. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  301. ;   interrupts possibly enabled.
  302. ; Exit with nc if ok, or else cy if error, dh set to error number.
  303. ;   es:di and interrupt enable flag preserved on exit.
  304. as_send_pkt:
  305.     ret
  306.  
  307.     public    drop_pkt
  308. ; Drop a packet from the queue.
  309. ; Enter with es:di -> iocb.
  310. drop_pkt:
  311.     assume    ds:nothing
  312.     ret
  313.  
  314.     public    xmit
  315. ; Process a transmit interrupt with the least possible latency to achieve
  316. ;   back-to-back packet transmissions.
  317. ; May only use ax and dx.
  318. xmit:
  319.     assume    ds:nothing
  320.     ret
  321.  
  322.  
  323.     public    send_pkt
  324. send_pkt:
  325. ;enter with ds:si -> packet, cx = packet length.
  326. ;exit with nc if ok, or else cy if error, dh set to error number.
  327.     assume    ds:nothing
  328. ; get txblk length                          
  329.     inc    cx
  330.     and    cl, 0feh
  331.     cmp    CX, RUNT
  332.     jnb    length_ok
  333.     mov    cx, RUNT
  334. length_ok:
  335.     cmp    cx, GIANT
  336.     jbe    length1_ok
  337.     mov    dh, NO_SPACE
  338.     stc    
  339.     jmp    count_out_err
  340. length1_ok:
  341. ;new stuff
  342.     mov    AX, CX
  343.     wr_NE    TBCR0            ; Transmit byte count
  344.     mov    al, ah
  345.     wr_NE    TBCR1
  346.     mov    al, 0
  347.     wr_NE    RSAR0
  348.     mov    al, 40h
  349.     wr_NE    RSAR1
  350.     mov    ax, cx
  351.     wr_NE    RBCR0            ; Remote byte count
  352.     mov    al, ah
  353.     wr_NE    RBCR1
  354.  
  355. ; Clear out DMA complete interrupt
  356.     mov    al, MSK_PG0        
  357.     wr_NE    CMDR
  358.     mov    al, 40h
  359.     wr_NE    ISR
  360.  
  361.     mov    al, MSK_DMA_WR
  362.     wr_NE    CMDR
  363.  
  364.     mov    DX, CS:io_addr
  365.     add    DX, RACK        ; DX has address NE/2 Port window 
  366.  
  367.     shr    cx, 1
  368.     rep    outsw
  369.  
  370.     xor    cx, cx            ; Prevent infinite loop
  371. WaitForDMAComplete:
  372.     rd_NE    ISR
  373.     test    al, 40h
  374.     jnz    DMAComplete
  375.     loop    WaitForDMAComplete
  376.  
  377. DMAComplete:
  378.     mov    al, MSK_TXP
  379.     wr_NE    CMDR
  380.     clc
  381. exit_now:
  382.     ret
  383.  
  384.  
  385.     public    get_address
  386. get_address:
  387. ;get the address of the interface.
  388. ;enter with es:di -> place to get the address, cx = size of address buffer.
  389. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  390.     assume    ds:code
  391.     cmp cx,    EADDR_LEN    ; Caller wants a reasonable length?
  392.     jb    get_addr_x    ; No, fail.
  393.     mov cx,    EADDR_LEN    ; Yes. Set count for loop
  394.     mov    si, offset cs:my_eaddr
  395.     cld            ; Make sure string mode is right
  396.     rep    movsb
  397.     mov cx,    EADDR_LEN    ; Tell caller how many bytes we fed him
  398.     clc            ; Carry off says success
  399.     ret
  400. get_addr_x:
  401.     stc            ; Tell caller our addr is too big for him
  402.     ret
  403.  
  404.  
  405.     public    set_address
  406. set_address:
  407. ;enter with ds:si -> Ethernet address, CX = length of address.
  408. ;exit with nc if okay, or cy, dh=error if any errors.
  409. ;This proc will set the first CX bytes of the ethernet address, leaving
  410. ; the rest unchanged.
  411.     assume    ds:nothing
  412.  
  413.     cmp    cx, 6
  414.     jbe    set1
  415.     mov    dh, BAD_ADDRESS
  416.     stc
  417.     ret
  418. set1:
  419.     push    es
  420.     push    di
  421.     mov    di, offset my_eaddr
  422.     mov    ax, cs
  423.     mov    es, ax
  424.  
  425.     mov    al, 61h
  426.     wr_NE    CMDR
  427.     mov    DX, CS:io_addr
  428.     add    DX, PAR0        ; DX has address 8390 Phys Address Reg
  429. AddressToChip1:
  430.     lodsb
  431.     out    dx, al
  432.     mov    es:[di], al
  433.     inc    di
  434.     inc    dx
  435.     nop
  436.     nop
  437.     nop    
  438.     nop
  439.     loop    AddressToChip1
  440.     pop    di
  441.     pop    es
  442.  
  443.     mov     al, 21h
  444.     wr_NE     CMDR
  445.     clc
  446.     ret
  447.  
  448. ; Routines to set address filtering modes in the DS8390
  449. ;    This was lifted from R. Clements' WD PD
  450. rcv_mode_1:     ; Turn off receiver
  451.     mov al,    MSK_MON      ; Set to monitor for counts but accept none
  452.     jmp short rcv_mode_set
  453. rcv_mode_2:     ; Receive only packets to this interface
  454.     mov al, 0               ; Set for only our packets
  455.     jmp short rcv_mode_set
  456. rcv_mode_3:     ; Mode 2 plus broadcast packets (This is the default)
  457.     mov al,    MSK_AB     ; Set four ours plus broadcasts
  458.     jmp short rcv_mode_set
  459. rcv_mode_4:     ; Mode 3 plus selected multicast packets
  460.     mov al,    MSK_AB+MSK_AM ; Ours, bcst, and filtered multicasts
  461.     mov     mcast_all_flag,0
  462.     jmp short rcv_mode_set
  463. rcv_mode_5:     ; Mode 3 plus ALL multicast packets
  464.     mov al,    MSK_AB+MSK_AM; Ours, bcst, and filtered multicasts
  465.     mov     mcast_all_flag,1
  466.     jmp short rcv_mode_set
  467. rcv_mode_6:     ; Receive all packets (Promiscuous physical plus all multi)
  468.     mov al,    MSK_AB+MSK_AM+MSK_PRO
  469.     mov     mcast_all_flag,1
  470. rcv_mode_set:
  471.     push    ax              ; Hold mode until masks are right
  472.     call    set_8390_multi  ; Set the multicast mask bits in chip
  473.     pop     ax
  474.     WR_NE    RCRWD
  475.     mov     rxcr_bits,al    ; Save a copy of what we set it to
  476.     ret
  477.  
  478.     public    set_multicast_list
  479. set_multicast_list:
  480. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  481. ;return nc if we set all of them, or cy,dh=error if we didn't.
  482.     mov    dh,NO_MULTICAST
  483.     stc
  484.     ret
  485.  
  486. ; Set the multicast filter mask bits in case promiscuous rcv wanted
  487. ;    This was lifted from R. Clements' WD PD
  488. set_8390_multi:
  489.     
  490.     mov    al,MSK_RD2+MSK_PG1
  491.     WR_NE    CMDR 
  492.     mov    cx,8        ; Eight bytes of multicast filter
  493.     mov    si,offset mcast_list_bits  ; Where bits are, if not all ones
  494.     push    cs
  495.     pop     ds
  496.     cli            ; Protect from irq changing page bits
  497.  
  498.     mov    DX, CS:io_addr
  499.     add    DX, MAR0
  500.     mov    al,mcast_all_flag  ; Want all ones or just selected bits?
  501.     or    al,al
  502.     jz    set_mcast_2     ; z = just selected ones
  503.     mov    al,0ffh        ; Ones for filter
  504. set_mcast_all:
  505.     out    dx, al
  506.     inc    dl        ; Step to next one
  507.     jmp    $+2        ; limit chip access rate
  508.     loop    set_mcast_all
  509.     jmp short set_mcast_x
  510.  
  511. set_mcast_2:
  512.     lodsb                   ; Get a byte of mask bits
  513.     out    dx,al        ; Write a mask byte
  514.     inc    dl        ; Step to next I/O register
  515.     jmp    $+2        ; limit chip access rate
  516.     loop    set_mcast_2
  517. set_mcast_x:
  518.     mov    al, MSK_RD2+MSK_PG0
  519.     WR_NE    CMDR
  520.     sti            ; OK for interrupts now
  521.     ret
  522.  
  523.  
  524.     public    terminate
  525. terminate:
  526.     ret
  527.  
  528.  
  529.     public    get_multicast_list
  530. get_multicast_list:
  531. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  532. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  533. ;return cy, NO_MULTICAST if we don't implement multicast.
  534.     mov    dh,NO_MULTICAST
  535.     stc
  536.     ret
  537.  
  538.  
  539.     public    reset_interface
  540. reset_interface:
  541. ;reset the interface.
  542.     assume    ds:code
  543.     mov    al, MSK_STP + MSK_RD2    
  544.     wr_NE    CMDR
  545.     mov al,    0ffh        ; Clear all pending interrupts
  546.     wr_NE    ISR
  547.     xor al,    al        ; Turn off all enables
  548.     wr_NE    IMR
  549.     wr_NE    NERESET        ; Hard reset NE/2
  550.     wr_NE    NERESET
  551.     wr_NE    NERESET
  552.     wr_NE    NERESET
  553.     wr_NE    NERESET
  554.     wr_NE    NERESET
  555.     wr_NE    NERESET
  556.     wr_NE    NERESET
  557.  
  558.     rd_NE    NERESET
  559.  
  560.     mov    al, 21h
  561.     wr_NE    CMDR
  562.     ret
  563.  
  564.  
  565. ;called when we want to determine what to do with a received packet.
  566. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  567. ;It returns with es:di = 0 if don't want this type or if no buffer available.    
  568.     extrn    recv_find: near
  569.  
  570. ;called after we have copied the packet into the buffer.
  571. ;enter with ds:si ->the packet, cx = length of the packet.
  572.     extrn    recv_copy: near
  573.  
  574.     extrn    count_in_err: near
  575.     extrn    count_out_err: near
  576.  
  577.  
  578.     public    recv
  579. recv:
  580. ;called from the recv isr.  All registers have been saved, and ds=cs.
  581. ;Actually, not just receive, but all interrupts come here.
  582. ;Upon exit, the interrupt will be acknowledged.
  583.     assume    ds:code
  584.  
  585. ; read irq status register
  586.     mov    al, MaskByte
  587.     wr_NE    IMR
  588.     sti
  589. rd_isr:
  590.     rd_NE    ISR            ; read isr into AL
  591.     and    AL, 3Fh            ; check bit0-bit5, if all 1's no irq
  592.     cmp    AL, 0            ; if any irq
  593.     jne    tst_ovw            ; some irq
  594.     cli
  595.     mov    al, UnmaskByte
  596.     wr_NE    IMR
  597.     ret                ; no more irq, exit
  598.  
  599. ; process OVW    (OVW = 1)       
  600. ;    may report error here
  601. tst_ovw:
  602.     test    AL, MSK_OVW        ; if OVW irq
  603.     jnz    prcs_ov            ; OVW (OVW = 1) 
  604.     jmp    test_rx            ; no OVW (OVW = 0) 
  605.  
  606. ; **************************************************************
  607. ; follow the DP8390 datasheet addendum to handle the buff ring overflow
  608. prcs_ov:
  609. ; 1. issue a STOP mode command
  610.     mov    AL, MSK_STP + MSK_RD2
  611.     wr_NE    CMDR
  612. ; 6. remove one packet from the ring
  613.     rd_NE    BNRY            ; BNRY in AL
  614.     add    AL, 1            ; start page of frm in AL
  615.     cmp    AL, STOP_PG        ; check boundary
  616.         jne    get1
  617.     mov    AL, START_PG        
  618. ; ring not empty
  619. get1:
  620.     mov    BH, AL            ; BX has the rx_frm pointer
  621.     mov    al, SIZE ReceiveHeader
  622.     wr_NE    RBCR0
  623.     xor    al, al
  624.     wr_NE    RBCR1
  625.     wr_NE    RSAR0
  626.     mov    al, bh
  627.     wr_NE    RSAR1
  628.     mov    al, MSK_DMA_RD
  629.     wr_NE    CMDR
  630.  
  631.     mov    DX, CS:io_addr
  632.     add    DX, RACK        ; DX has address NE/2 Port window 
  633.     mov    di, OFFSET ReceiveHeader
  634.     mov    ax, cs
  635.     mov    es, ax
  636.     mov    cx, SIZE ReceiveHeader
  637.     shr    cx, 1    
  638. Receive1:
  639. rep    insw
  640.  
  641. SkipReceive1:
  642.     mov    bx, offset ReceiveHeader
  643.     mov    AL, CS:[BX]        ; AL has the status byte
  644.     test    AL, SMK_PRX        ; if rx good
  645.     jz    fd_bnr            ; rx error, drop frm by forward bnry
  646.  
  647. ; good frm, call _rcv_frm
  648.     call     _rcv_frm           
  649.  
  650. fd_bnr:                    ;drop frm by forward BNRY
  651.     mov    al, cs:ReceiveHeader.RNextBuffer    ; al = next pointer 
  652.     sub    AL, 1            ; new BNRY in AL
  653.     cmp    AL, START_PG        ; check boundary
  654.     jae    wrbnr            ; unsigned arithmetic
  655.     mov    AL, STOP_PG - 1        ;
  656. ;    dec    AL            ;
  657. wrbnr:
  658.     wr_NE    BNRY
  659. ; 2. clear the remote byte count registers (RBCR0,RBCR1)
  660.     xor    AL, AL
  661.     wr_NE    RBCR0
  662.     wr_NE    RBCR1
  663. ; 3. poll the ISR for the RST bit
  664. plisr:
  665.     mov    cx, 0ffffh
  666.     rd_NE    ISR
  667.     test    AL, MSK_RST
  668.     jnz    plisr_ok
  669.     loop    plisr        ; keep polling until the RST bit set
  670. ; 4. place the NIC in loopback mode (mode 1 or 2) by writing 02 or 04 to TCR
  671. plisr_ok:
  672.     mov    AL, 02h        ; put it in mode 2 (internal loopback)
  673.     wr_NE    TCR
  674. ; 5. issue start mode command
  675.     mov    AL, MSK_STA + MSK_RD2
  676.     wr_NE    CMDR
  677. ; 7. out from loopback mode by writing 00 to TCR
  678.     xor    AL, AL
  679.     wr_NE    TCR        ; normal operation configuration
  680. ; clear OVW in ISR              
  681.     mov    AL, MSK_OVW 
  682.     wr_NE    ISR            ; clear OVW
  683.     call    count_in_err        ; increment overflow counter
  684.     jmp    rd_isr            ; back to the top
  685.  
  686.  
  687. ; end of the modification 
  688. ; *****************************************************
  689. ;    
  690. ;process PRX and RXE
  691. ;
  692. test_rx:        
  693.     test     AL, MSK_RXE        
  694.     jnz    prcs_rxe        ; RXE = 1
  695.     test      AL, MSK_PRX    
  696.     jnz    prcs_rx                 ; PRX = 1
  697.     jmp    test_tx
  698.  
  699. prcs_rxe:
  700.     call    count_in_err
  701.     mov    al, MSK_RXE
  702.     wr_NE    ISR
  703.     jmp    rd_isr
  704. prcs_rx:
  705.     mov    AL, MSK_PG1 + MSK_RD2    ; read CURR reg
  706.     wr_NE    CMDR
  707.     rd_NE    CURR
  708.     mov    BL, AL            ; CURR in BL 
  709.     mov    AL, MSK_PG0 + MSK_RD2    ; read BNRY reg
  710.     wr_NE  CMDR
  711.     rd_NE    BNRY            ; BNRY in AL
  712.     add    AL, 1            ; start page of frm in AL
  713.     cmp    AL, STOP_PG         ; check boundary
  714.     jne    go_cmp
  715.     mov    AL, START_PG         ;         
  716. go_cmp:
  717.     cmp    AL, BL            
  718.     jne    Ring_Not_Empty
  719.     jmp    rd_isr            ; buff ring empty
  720.  
  721. Ring_Not_Empty:
  722.     wr_NE    RSAR1
  723.     xor    al, al
  724.     wr_NE    RBCR1
  725.     wr_NE    RSAR0
  726.     mov    al, SIZE ReceiveHeader
  727.     wr_NE    RBCR0
  728.     mov    al, MSK_DMA_RD
  729.     wr_NE    CMDR
  730.  
  731.     mov    DX, CS:io_addr
  732.     add    DX, RACK        ; DX has address NE/2 Port window 
  733.     mov    di, OFFSET ReceiveHeader
  734.     mov    ax, cs
  735.     mov    es, ax
  736.     mov    cx, SIZE ReceiveHeader
  737.     shr    cx, 1
  738.  
  739. Receive2:
  740. rep    insw
  741.  
  742. SkipReceive2:
  743.     mov    bx, offset ReceiveHeader
  744.     mov    AL, CS:[BX]        ; AL has the status byte
  745.     test    AL, SMK_PRX        ; if rx good
  746.     jz    fd_bnry            ; rx error, drop frm by forward bnry
  747.  
  748. ; good frm, call _rcv_frm
  749.        call     _rcv_frm           
  750.  
  751. fd_bnry:                ; drop frm by forward BNRY
  752.     mov    al, CS:ReceiveHeader.RNextBuffer    ; al = next pointer 
  753.     sub    AL, 1            ; new BNRY in AL
  754.     cmp    AL, START_PG        ; check boundary
  755.     jae    wrbnry            ; unsigned arithmetic
  756.     mov    AL, STOP_PG - 1        ;
  757.  
  758. wrbnry:
  759.     wr_NE    BNRY
  760.     mov    al, MSK_PRX
  761.     wr_NE    ISR
  762.     jmp    prcs_rx     
  763.  
  764. ;process PTX and TXE
  765. test_tx:
  766.     test      AL, MSK_PTX    
  767.     jnz    prc_ptx                 ; PTX = 1
  768.     test     AL, MSK_TXE        
  769.     jnz    prc_txe            ; TXE = 1
  770.     jmp    test_cnt
  771.       
  772.  
  773. ; process tx good, update txok, lostcrs, collsn
  774. prc_ptx:                ; tx good 
  775.     rd_NE    TSR
  776.     test    AL, SMK_CRS        ; is crs set in TSR
  777.     jz    nocrs            ; no               
  778. nocrs:    
  779.     rd_NE    NCR            ; read number of collision in AL
  780.     mov    AL, MSK_PTX
  781.     wr_NE    ISR            ; clear PTX
  782.     jmp    rd_isr
  783.  
  784. ; process tx error, update .txbad .underrun
  785. prc_txe:                ; tx bad
  786.     call    count_out_err    
  787.     rd_NE    TSR
  788.     test    AL, SMK_FU        ; it fu set in TSR
  789.     jz    nofu            ; no               
  790. nofu:                                  
  791.         mov    AL, MSK_TXE
  792.     wr_NE    ISR            ; clear PTX
  793.     jmp    rd_isr
  794.  
  795. ; process counter overflow, update .algerr .crcerr .???(missed pkt)
  796. test_cnt:
  797.     test      AL, MSK_CNT    
  798.     jnz    prc_cnt            ; yes, process cnt
  799.     jmp    rd_isr                 ; no CNT irq, back to the top
  800. ; process CNT            
  801. prc_cnt:
  802.     mov    AL, MSK_CNT
  803.     wr_NE    ISR            ; clear CNT
  804.     jmp    rd_isr            ; back to the top
  805.  
  806. ; End of RECV
  807.  
  808. _rcv_frm:
  809.     
  810. ; read byte count 
  811.     mov     cx, cs:ReceiveHeader.RByteCount    ; Extract size of frame
  812.     cmp    CX, 5dch
  813.     jna    rxlen_ok
  814.     jmp    rcv_ret
  815. rxlen_ok:
  816.     sub    CX, 4            ; 4 control bytes
  817.     mov    AX, cs
  818.     mov    ES, AX
  819.     mov     di, offset cs:ReceiveHeader.RPacketLength
  820.     mov    dl, BLUEBOOK        ;default 
  821.     mov    ax, es:[di]
  822.     xchg    ah, al
  823.     cmp     ax, 1500
  824.     ja    BlueBookPacket
  825.     mov    di, offset cs:ReceiveHeader.RChecksum
  826.     mov    dl, IEEE8023
  827. BlueBookPacket:
  828.  
  829.     push    cx            ; Save frame size
  830.     push    es
  831.  
  832.     mov ax,    cs            ; Set ds = code
  833.     mov ds,    ax
  834.     assume    ds:code
  835.     call    recv_find        ; See if type and size are wanted
  836.                     ;     CX = packet length
  837.                     ;    ES:DI = packet type
  838.                     ;    ES:DI = packet type
  839.  
  840.     pop    ds            ; RX page pointer in ds now
  841.     assume    ds:nothing
  842.     pop    cx
  843.  
  844.     cld                ; Copies below are forward
  845.     mov ax,    es            ; Did recv_find give us a null pointer?
  846.     or  ax,    di            ; ..
  847.     je    no_buff            ; If null, don't copy the data    
  848. has_buf:  
  849.  
  850. ;Tell DMA to copy the whole packet for us
  851.     mov    ax, 4
  852.     wr_NE    RSAR0        ; Don't copy  4 8390 control bytes
  853.     mov    ax, cx        ; CX has byte count
  854.     wr_NE    RBCR0        ; LSB first
  855.     mov    al, ah
  856.     wr_NE    RBCR1        ; Now MSB
  857.  
  858.     mov    al, MSK_DMA_RD  ; Issue DMA read command
  859.     wr_NE    CMDR
  860.  
  861. ; copy from NE/2 on board memory using the window RACK
  862. ; use IN and stosb to do the copy, IN -> AX -> ES:DI (CX has byte count)                        
  863.  
  864. copynow:
  865.     push    cx        ; We will want the count and pointer
  866.     push    es        ;  to hand to client after copying,
  867.     push    di        ;  so save them at this point
  868.  
  869.     mov    DX, CS:io_addr
  870.     add    DX, RACK        ; DX has address NE/2 Port window (?)
  871.  
  872.     mov    si, cx
  873.     shr    cx, 1
  874.     rep    insw
  875.     test    si, 1
  876.     jz    call_rc
  877.     in    ax, dx
  878.     stosb
  879. call_rc:
  880.     pop    si            ; Recover pointer to destination
  881.     pop    ds            ; Tell client it's his source
  882.     pop    cx            ; And it's this long
  883.     assume    ds:nothing
  884.     call    recv_copy        ; Give it to him
  885.     jmp    short rcv_ret
  886.  
  887. ; no system buff availble to hold rx frm
  888. no_buff:
  889. rcv_ret:
  890.     push    cs        ; Put ds back in code space
  891.     pop    ds        ; ..
  892.     assume    ds:code
  893.     ret
  894.  
  895.  
  896.  
  897.     public    recv_exiting
  898. recv_exiting:
  899. ;called from the recv isr after interrupts have been acknowledged.
  900. ;Only ds and ax have been saved.
  901.     assume    ds:nothing
  902.     ret
  903.  
  904.  
  905. ;any code after this will not be kept after initialization.
  906. end_resident    label    byte
  907.  
  908.  
  909.     public    usage_msg
  910. usage_msg    db    "usage: NE2 <packet_int_no>",CR,LF,'$'
  911.  
  912.     public    copyright_msg
  913. copyright_msg    db    "Packet driver for NE/2 version "
  914.         db    '0'+majver,".",'0'+version,CR,LF
  915.         db    "Portions Copyright 1990, Eric Henderson, BYU",CR,LF,'$'
  916. int_no_name    db    "Interrupt number ",'$'
  917. io_addr_name    db    "I/O port ",'$'
  918. no_board_msg:
  919.     db    "NE/2 apparently not present at this IO address.",CR,LF,'$'
  920. HardwareFailure:
  921.     db    "The NE/2 is not responding.",CR,LF,'$'
  922. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  923.  
  924.     extrn    set_recv_isr: near
  925.  
  926.  
  927. ;enter with si -> argument string, di -> word to store.
  928. ;if there is no number, don't change the number.
  929. ;    extrn    decout: near
  930. ;    extrn    hexout: near
  931.  
  932.     public    parse_args
  933. print_args:
  934.     mov    dx,offset int_no_name
  935.     mov    ah,9
  936.     int    21h
  937.     mov    di,offset int_no
  938.     mov    ax,[di]            ;print the number in hex.
  939.     mov    dx,[di+2]
  940. ;    call    hexout
  941.     mov    dl,' '
  942.     mov    ah, 2
  943.     int    21h
  944.     mov    dl,'('
  945.     mov    ah, 2
  946.     int    21h
  947.     mov    ax,[di]            ;print the number in decimal.
  948.     mov    dx,[di+2]
  949. ;    call    decout
  950.     mov    dl,')'
  951.     mov    ah, 2
  952.     int    21h
  953.     mov    dl,CR
  954.     mov    ah, 2
  955.     int    21h
  956.     mov    dl,LF
  957.     mov    ah, 2
  958.     int    21h
  959.     mov    dx,offset io_addr_name
  960.     mov    ah,9
  961.     int    21h
  962.     mov    di,offset io_addr
  963.     mov    ax,[di]            ;print the number in hex.
  964.     mov    dx,[di+2]
  965. ;    call    hexout
  966.     mov    dl,' '
  967.     mov    ah, 2
  968.     int    21h
  969.     mov    dl,'('
  970.     mov    ah, 2
  971.     int    21h
  972.     mov    ax,[di]            ;print the number in decimal.
  973.     mov    dx,[di+2]
  974. ;    call    decout
  975.     mov    dl,')'
  976.     mov    ah, 2
  977.     int    21h
  978.     mov    dl,CR
  979.     mov    ah, 2
  980.     int    21h
  981.     mov    dl,LF
  982.     mov    ah, 2
  983.     int    21h
  984. parse_args:
  985.     ret
  986.  
  987.     extrn    etopen_diagn: byte
  988.  
  989. BoardNotResponding:
  990.     mov    dx, offset HardwareFailure
  991.     mov    etopen_diagn, 35
  992.     jmp    short error_wrt
  993. bad_cksum:
  994. no_memory:
  995.     mov    dx,offset no_board_msg
  996.     mov    etopen_diagn,37
  997. error_wrt:
  998.     mov    ah,9
  999.     int    21h
  1000.     stc
  1001.     ret
  1002.  
  1003. SlotSelectRegister        equ    96h
  1004. POS0                equ    100h
  1005. POS1                equ    101h
  1006. POS2                equ    102h
  1007. NE2ID                equ    7154h
  1008.  
  1009. IRQConfiguration        label    byte    ;possible IRQ settings
  1010.                 db    3
  1011.                 db    4
  1012.                 db    5
  1013.                 db    9
  1014.  
  1015. IOConfiguration          label    word    ;possible I/O Base addresses
  1016.                 dw    1000h
  1017.                 dw    2020h
  1018.                 dw    8020h
  1019.                 dw    0A0A0h
  1020.                 dw    0B0B0h
  1021.                 dw    0C0C0h
  1022.                 dw    0C3D0h
  1023.  
  1024.     public    etopen
  1025. etopen:
  1026. ;if all is okay,
  1027.     cli                    ;Find the NE/2 NIC
  1028.     mov     cl, 7                ; channel position (8=1st slot
  1029.                         ; F=8th slot)
  1030. NextSlot:
  1031.     inc    cl
  1032.     cmp    cl,10h                ;check 8 I/O slots
  1033.     jne    NoHardwareFailure
  1034.     jmp    BoardNotResponding
  1035. NoHardwareFailure:
  1036.     mov    al, cl
  1037.     out    SlotSelectRegister, al        ;select card slot
  1038.     mov     dx, POS1
  1039.     in    al, dx                ;check for NE2 ID
  1040.     mov    ah, al
  1041.     mov    dx, POS0
  1042.     in    al, dx
  1043.     cmp    ax, NE2ID
  1044.     jne    NextSlot
  1045.  
  1046.     mov    dx, POS2            ;read configuration port
  1047.     in    al, dx                    
  1048.  
  1049.     test    al, 01                ;test to see if card enable
  1050.     jz    NextSlot            ; bit is set
  1051.  
  1052.     mov    bl, al
  1053.     and    bx, 000Eh            ;mask all but I/O base addr.
  1054.  
  1055.     jz    NextSlot            ;check next slot if no option
  1056.                         ; setting in POS 2
  1057.     dec    bx
  1058.     dec    bx
  1059.     mov    dx, IOConfiguration[bx]        ; IO address
  1060.     mov    io_addr, dx            ;save the base I/O address
  1061.  
  1062.     test    al, 10h                ;if boot prom enabled then
  1063.  
  1064. SetIRQ:
  1065.     shr    al, 5                ;load the hardware config.
  1066.     and    ax, 3                ; table with the IRQ line
  1067.     mov    bx, ax                ; value and string
  1068.     mov    dl, IRQConfiguration[bx]
  1069.     mov    int_no, dl            ;save interrupt level
  1070. ;    call    print_args
  1071.  
  1072. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  1073. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  1074.     mov    cl,33
  1075.     mov    ax,0ffffh
  1076.     shl    ax,cl
  1077.     jz    not_186
  1078.     mov    is_186,1
  1079.     mov    dx,offset using_186_msg
  1080.     mov    ah,9
  1081.     int    21h
  1082. not_186:
  1083.  
  1084.     call    set_recv_isr    ; Put ourselves in interrupt chain
  1085.  
  1086.     ; reset NE/2 board 
  1087.     cli
  1088.     wr_NE    NERESET
  1089.     wr_NE    NERESET
  1090.     wr_NE    NERESET
  1091.     wr_NE    NERESET
  1092.     wr_NE    NERESET
  1093.     wr_NE    NERESET
  1094.     wr_NE    NERESET
  1095.     wr_NE    NERESET
  1096.  
  1097.     rd_NE    NERESET
  1098.  
  1099.     mov    al, 21h
  1100.     wr_NE    CMDR
  1101.  
  1102.     ; Test to see if we're OK
  1103.     rd_NE    CMDR
  1104.     cmp    al, 21h
  1105.     je    WeBeOK
  1106.     jmp    BoardNotResponding
  1107.  
  1108. WeBeOK:
  1109.     mov    al, 49h            ;Word mode
  1110.     wr_NE    DCR        
  1111.     mov    al, 0
  1112.     wr_NE    RBCR0
  1113.     wr_NE    RBCR1
  1114.     mov    al, 4
  1115.     wr_NE    RCRWD
  1116.     mov    al, 02
  1117.     wr_NE    TCR        
  1118.     mov    al, START_PG
  1119.     wr_NE    PSTART        
  1120.     wr_NE    BNRY        
  1121.     mov    al, STOP_PG
  1122.     wr_NE    PSTOP        
  1123.  
  1124.     mov    al, 0ffh
  1125.     wr_NE    ISR        
  1126.     mov    al, 01fh
  1127.     wr_NE    IMR
  1128.  
  1129.     mov    al, 61h
  1130.     wr_NE    CMDR        
  1131.     mov    al, START_PG + 1
  1132.     wr_NE    CURR
  1133.     mov    al, 21h
  1134.     wr_NE    CMDR        
  1135.  
  1136.  
  1137.  
  1138.     mov    DX, CS:io_addr
  1139.     add    DX, RACK        ; DX has address NE/2 Port window 
  1140.  
  1141.     mov     bx, -1                ;setup for Nic's memory test
  1142.  
  1143.     mov    bp, CS:io_addr
  1144.       call    RAMTest              ;16 bit memory test
  1145.  
  1146.         jz    memory_OK            ;if error, report it
  1147.     jmp    no_memory
  1148.  
  1149. memory_OK:
  1150.     ; set up my_eaddr from addr ROM 
  1151.     mov    al, 12            ;read 6 bytes from PROM (word mode=12)
  1152.     wr_NE    RBCR0
  1153.     mov    al, 0
  1154.     wr_NE    RBCR1
  1155.     wr_NE    RSAR0
  1156.     wr_NE    RSAR1
  1157.     mov    al, MSK_DMA_RD
  1158.     wr_NE    CMDR
  1159.  
  1160.     mov    DX, CS:io_addr
  1161.     add    DX, RACK        ; DX has address NE/2 Port window (?)
  1162.     mov    di, OFFSET my_eaddr
  1163.     mov    ax, cs
  1164.     mov    es, ax
  1165.     mov    cx, 6
  1166. GetEnetAddress:
  1167.     in    al, dx
  1168.     stosb
  1169.     loop    GetEnetAddress
  1170.  
  1171. ModeCheckDone:
  1172.     mov    ax, cs
  1173.     mov    ds, ax
  1174.     mov    si, OFFSET my_eaddr
  1175.     mov    cx, 6
  1176.     call    set_address
  1177.  
  1178.     mov     al, 21h
  1179.     wr_NE     CMDR
  1180.  
  1181. SetTXPage:
  1182.     mov     al,0C0h                        ;C000h is used as TX
  1183.         wr_NE    TPSR                ;page because of
  1184.                             ;spurious writes to 
  1185.                         ;Ram during transmits
  1186.                         ;when collisions occur
  1187.     mov    al, 22h
  1188.     jmp    $+2
  1189.     wr_NE    CMDR    
  1190.  
  1191.     mov    al, 0
  1192.     wr_NE    TCR
  1193.  
  1194.     mov    al,0                ;deselect all I/O channels
  1195.     out    SlotSelectRegister,al
  1196.  
  1197.     mov    dx,offset end_resident
  1198.     sti
  1199.     clc
  1200.     ret
  1201.  
  1202. ;**********************************************************************
  1203. ;
  1204. ;    RAM Test
  1205. ;
  1206. ;    assumes:
  1207. ;        BX    has the test value
  1208. ;        BP    points to IOBase
  1209. ;        NIC (8390) has been set to ignore activity on wire
  1210. ;          (loopback mode) and is set to page 0
  1211. ;
  1212. ;    returns:
  1213. ;        Z flag set if no error
  1214. ;        BP    preserved.
  1215. ;        NIC set to page 0
  1216. ;
  1217. ;**********************************************************************
  1218.  
  1219. RAMTest    proc    near
  1220.  
  1221.     lea    dx, [bp].RemoteStartAddress0    ;point at start of RAM
  1222.     xor    al, al
  1223.     out    dx, al
  1224.         inc     dx
  1225.     mov    al, 40h
  1226.     out    dx, al
  1227.  
  1228.     inc    dx                ;set byte count=16k
  1229.     xor    al, al                ; (both 8k RAM chips)
  1230.     out    dx, al
  1231.     inc    dx
  1232.     mov    al, 40h
  1233.     out    dx, al
  1234.  
  1235.     lea    dx, [bp].Command        ;write in all RAM locations
  1236.     mov    al, MSK_DMA_WR            ; what we send
  1237.     out    dx, al
  1238.  
  1239.     lea    dx, [bp].DataPort        ;point at Nic's data port
  1240.  
  1241.     mov    cx, 2000h            ;set count to 8k words
  1242.  
  1243.     mov    ax, bx                ;read in test value
  1244.  
  1245. WriteLoop:
  1246.     inc    ax                ;adjust test pattern
  1247.     out    dx, ax                ;send it out to Nic
  1248.     loop    WriteLoop
  1249.  
  1250.                         ;now read back and compare
  1251.                         ; test pattern from NIC
  1252.  
  1253.     lea    dx, [bp].RemoteStartAddress0    ;point at start of RAM
  1254.     xor    al, al
  1255.     out    dx, al
  1256.         inc     dx
  1257.     mov    al, 40h
  1258.     out    dx, al
  1259.  
  1260.     inc    dx                ;set byte count = 16k
  1261.     xor    al, al
  1262.     out    dx, al
  1263.     inc    dx
  1264.     mov    al, 40h
  1265.     out    dx, al
  1266.  
  1267.     lea    dx, [bp].Command        ;tell NIC to send back test
  1268.     mov    al, MSK_DMA_RD            ; pattern
  1269.     out    dx, al
  1270.  
  1271.     lea    dx, [bp].DataPort        ;point at Nic's data port
  1272.  
  1273.     mov    cx, 2000h            ;setup loop
  1274.  
  1275. ReadLoop:
  1276.     in    ax, dx                ;read in test pattern and
  1277.     inc    bx                ; compare with original
  1278.     cmp    bx, ax
  1279.  
  1280.     loopz    ReadLoop
  1281.  
  1282.     ret                    ;zero flag set if memory error
  1283.  
  1284. RAMTest    endp
  1285.  
  1286.     public    print_parameters
  1287. print_parameters:
  1288. ;echo our command-line parameters
  1289.     ret
  1290.  
  1291.  
  1292. code    ends
  1293.  
  1294.     end
  1295.